package com.frank.subject.domain.service.impl;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.frank.common.entity.PageInfo;
import com.frank.common.utils.LoginUtil;
import com.frank.config.redis.RedisUtil;
import com.frank.subject.common.enums.RedisStorageKey;
import com.frank.subject.common.enums.SubjectLikedStatusEnum;
import com.frank.subject.domain.convert.SubjectLikedBoConvert;
import com.frank.subject.domain.entity.SubjectLikedBo;
import com.frank.subject.domain.entity.SubjectLikedMessage;
import com.frank.subject.domain.service.SubjectLikedDomainService;
import com.frank.subject.infra.basic.entity.SubjectInfo;
import com.frank.subject.infra.basic.entity.SubjectLiked;
import com.frank.subject.infra.basic.service.SubjectInfoService;
import com.frank.subject.infra.basic.service.SubjectLikedService;
import org.apache.commons.collections4.MapUtils;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * @author Frank Zou
 * @version v0.0.1
 * @date 2025/3/12
 * @description
 */
@Service
public class SubjectLikedDomainServiceImpl implements SubjectLikedDomainService {

    private final SubjectLikedService subjectLikedService;

    private final SubjectInfoService subjectInfoService;

    private final RedisUtil<String, Integer> redisUtil;

    private final RocketMQTemplate rocketMQTemplate;


    public SubjectLikedDomainServiceImpl(
            SubjectLikedService subjectLikedService,
            SubjectInfoService subjectInfoService,
            RedisUtil<String, Integer> redisUtil,
            RocketMQTemplate rocketMQTemplate) {
        this.subjectLikedService = subjectLikedService;
        this.subjectInfoService = subjectInfoService;
        this.redisUtil = redisUtil;
        this.rocketMQTemplate = rocketMQTemplate;
    }

    @Override
    public Boolean add(SubjectLikedBo subjectLikedBo) {
        String field = buildSubjectLikedRedisKey(subjectLikedBo.getSubjectId().toString(), subjectLikedBo.getLikeUserId());
        redisUtil.putHash(RedisStorageKey.SUBJECT_LIKED.getKey(), field, 1);

        SubjectLikedMessage message = new SubjectLikedMessage();
        message.setLikeUserId(subjectLikedBo.getLikeUserId())
                .setSubjectId(subjectLikedBo.getSubjectId())
                .setStatus(subjectLikedBo.getStatus());
        rocketMQTemplate.convertAndSend("jc-club-subject-liked", JSON.toJSONString(message));


        String detailKey = RedisUtil.buildKey(RedisStorageKey.SUBJECT_LIKED_DETAIL.getKey(), subjectLikedBo.getSubjectId().toString(), subjectLikedBo.getLikeUserId());
        String countKey = RedisUtil.buildKey(RedisStorageKey.SUBJECT_LIKED_COUNT.getKey(), subjectLikedBo.getSubjectId().toString());
        if (SubjectLikedStatusEnum.LIKED.getCode().equals(subjectLikedBo.getStatus())) {
            redisUtil.increment(countKey, 1);
            redisUtil.set(detailKey, 1);
        } else {
            Integer count = redisUtil.get(countKey);
            if (Objects.nonNull(count) && count > 0) {
                redisUtil.increment(countKey, -1);
            }
            redisUtil.del(detailKey);
        }
        return true;
    }

    @Override
    public Boolean isLiked(String subjectId, String userId) {
        String key = RedisUtil.buildKey(RedisStorageKey.SUBJECT_LIKED_DETAIL.getKey(), subjectId, userId);
        return redisUtil.exist(key);
    }

    @Override
    public Integer getLikedCount(String subjectId) {
        String key = RedisUtil.buildKey(RedisStorageKey.SUBJECT_LIKED_COUNT.getKey(), subjectId);
        Integer count = redisUtil.get(key);
        if (Objects.nonNull(count)) {
            return count;
        }
        return 0;
    }

    @Override
    public void syncSubjectLiked() {
        Map<String, Integer> map = redisUtil.getHashAndDelete(RedisStorageKey.SUBJECT_LIKED.getKey());
        if (MapUtils.isEmpty(map)) {
            return;
        }
        List<SubjectLiked> list = new ArrayList<>();
        map.forEach((key, value) -> {
            SubjectLiked subjectLiked = new SubjectLiked();
            String[] arr = key.split(":");
            String subjectId = arr[0];
            String likeUserId = arr[1];
            subjectLiked.setSubjectId(Long.parseLong(subjectId));
            subjectLiked.setLikeUserId(likeUserId);
            subjectLiked.setStatus(value);
            list.add(subjectLiked);
        });

        subjectLikedService.saveBatch(list);

    }

    @Override
    public Page<SubjectLikedBo> getSubjectLikedPage(PageInfo pageInfo) {
        Page<SubjectLiked> page = new Page<>(pageInfo.getCurrent(), pageInfo.getPageSize());
        LambdaQueryWrapper<SubjectLiked> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(SubjectLiked::getStatus, LoginUtil.getLoginId())
                .eq(SubjectLiked::getStatus, SubjectLikedStatusEnum.LIKED.getCode());
        wrapper.orderByDesc(SubjectLiked::getCreatedTime);
        page = subjectLikedService.page(page, wrapper);
        Page<SubjectLikedBo> result = SubjectLikedBoConvert.INSTANCE.convertEntityPageToBoPage(page);
        result.getRecords().forEach(subjectLikedBo -> {
            LambdaQueryWrapper<SubjectInfo> subjectInfoQuery = Wrappers.lambdaQuery();
            subjectInfoQuery.select(SubjectInfo::getSubjectName);
            subjectInfoQuery.eq(SubjectInfo::getId, subjectLikedBo.getSubjectId());
            SubjectInfo subjectInfo = subjectInfoService.getOne(subjectInfoQuery);
            if (Objects.nonNull(subjectInfo)) {
                subjectLikedBo.setSubjectName(subjectInfo.getSubjectName());
            }
        });
        return result;
    }

    private String buildSubjectLikedRedisKey(String subjectId, String userId) {
        return subjectId + ":" + userId;
    }

}
